﻿using System;
using System.Threading;
using Draco.OWF.Metadata.DataBinding;
using Draco.OWF.RT.Engine.Worker;
using Draco.OWF.RT.Engine.Manager;
using Draco.OWF.RT.Engine.Impl;
using Draco.OWF.Metadata;
using Draco.OWF.Flow;
using System.Collections.Generic;

namespace Draco.OWF.RT.Engine
{
    public abstract class AbstractEngine:IEngine
    {
        protected ActivityManager _activityManager = new ActivityManager();
        protected WorkflowManager _workflowManger = new WorkflowManager();
        private JobManager _jobManager = new JobManager();
        private RunableFlowManager _flows = new RunableFlowManager();
        protected IEngineContext _context=null;

        public virtual void init(IEngineConfiguration config)
        {
            _activityManager.LoadActivities(config.ActivityRepo);
            _workflowManger.LoadProcessFromDirectory(config.ProcessesRepo);
            _flows.LoadJobFromRepository(config.JobRepo);
            _context = new EngineContext(this);
        }

        public WorkflowManager WorkflowManager
        {
            get { return _workflowManger; }
        }

        public ActivityManager ActivityManager
        {
            get { return _activityManager; }
        }
        public JobManager JobManager
        {
            get { return _jobManager; }
        }

        public virtual IJob CreateJob(String processId, BindingData Arguments, IJobContext parentContext)
        {
            WorkflowModel process = WorkflowManager.GetProcess(processId);
            if (process == null)
                throw new ArgumentException("cannot find process:"+ processId);
            return CreateJob(process, Arguments, parentContext);
        }

        public virtual IJob CreateJob(WorkflowModel process, BindingData Arguments)
        {
            return CreateJob(process, Arguments,null);
        }

        public virtual IJob CreateJob(WorkflowModel process, BindingData arguments,IJobContext parentContext)
        {
            if (process == null)
                throw new ArgumentNullException("process is null");
            IRunableFlow runableFlow = new RunableFlow(process,_context);
            _flows.Add(runableFlow);
            runableFlow.Run(parentContext);
            Thread.Sleep(500);
            return runableFlow.GetLastJob() ;
        }

        public virtual void Dispose()
        {

        }
    }
}
